package rest.jbpm.services;

import com.sun.jersey.multipart.FormDataParam;
import java.io.*;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import javax.ws.rs.*;
import javax.ws.rs.core.*;
import org.apache.commons.io.IOUtils;
import org.jbpm.api.ProcessDefinition;
import org.jbpm.pvm.internal.model.ProcessDefinitionImpl;
import org.jbpm.pvm.internal.query.ProcessDefinitionQueryImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import rest.jbpm.JbpmService;
import rest.jbpm.ProcessEngineException;
import rest.jbpm.repository.LatestDefinitions;
import rest.jbpm.wrappers.Definition;
import rest.jbpm.wrappers.Deployment;
import rest.jbpm.wrappers.lists.*;

@Path("repo")
public class RepositoryService extends JbpmService {
	
	
	private static final Logger log = LoggerFactory.getLogger(RepositoryService.class);
	private static File deploymentDir;
	@Context UriInfo uriInfo;
	
    static {    
        try {
            URL url = RepositoryService.class.getClassLoader().getResource("../..");
            deploymentDir =  new File(new File(url.toURI()).getParent(),"deployments");
            log.info("deployment url {}", deploymentDir);
            if(!deploymentDir.exists()) deploymentDir.mkdir();
            /*
            for(String f : deploymentDir.list( 
                    new FilenameFilter() {
                        public boolean accept(File dir, String fileName) {
                            return fileName.endsWith(".jpdl.xml");
                    }})) {
                log.info("definition found " + f);
                processEngine.getRepositoryService().createDeployment()
                        .addResourceFromFile(new File(deploymentDir,f)).deploy();
            }
             * 
             */
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
    }	
	
	public static File getDeploymentDir() {
		return deploymentDir;
	}

	@GET
	@Path("definitions")
	@Produces("text/xml")
	public DefinitionList getProcessDefinitions() {
		
		if(processEngine == null)
			throw new ProcessEngineException("Fire! fire! mayday! mayday! we're going down!.. JBPM process engine is down!");
		
		return new DefinitionList(processEngine.getRepositoryService()
                .createProcessDefinitionQuery()
                .orderAsc(ProcessDefinitionQueryImpl.PROPERTY_KEY)
                .orderDesc(ProcessDefinitionQueryImpl.PROPERTY_VERSION)
                .list(), uriInfo.getBaseUri().toString());

	}
    
    @GET
	@Path("latestDefinitions")
	@Produces("text/xml")
	public DefinitionList getLatestProcessDefinitions() {
		
        List<Definition> allDefinitions = getProcessDefinitions().getDefinitions();
        DefinitionList res = new DefinitionList(null, uriInfo.getBaseUri().toString());
        
        for(int i = 0; i < allDefinitions.size(); i++) {
            
            Definition def = allDefinitions.get(i);
            res.getDefinitions().add(def);
            i += def.getVersion() - 1;
        }
        
        return res;
	}
	
	@GET
	@Path("definition/{id}")
	@Produces("text/xml")
	public Definition getProcessDefinition(@PathParam("id") String id) {
		
		if(processEngine == null)
			throw new ProcessEngineException("Fire! fire! mayday! mayday! we're going down!.. JBPM process engine is down!");
		
		return new Definition(processEngine.getRepositoryService().createProcessDefinitionQuery().processDefinitionId(id).uniqueResult(), 
				uriInfo.getBaseUri().toString());
	}
	
	@GET
	@Path("definition/{id}/stats")
	@Produces("text/xml")
	public DurationList getStats(@PathParam("id") String id) {
		
		if(processEngine == null)
			throw new ProcessEngineException("Fire! fire! mayday! mayday! we're going down!.. JBPM process engine is down!");
		
		return new DurationList(processEngine.getHistoryService().avgDurationPerActivity(id));
	}

	@GET
	@Path("deployments")
	@Produces("text/xml")
	public DeploymentList getDeployments() {
		
		if(processEngine == null)
			throw new ProcessEngineException("Fire! fire! mayday! mayday! we're going down!.. JBPM process engine is down!");
		
		return new DeploymentList(processEngine.getRepositoryService().createDeploymentQuery().list());

	}
	
	@POST
	@Path("deploy")
	@Consumes("multipart/form-data")
	public Response deploy(@FormDataParam("file") InputStream file, @FormDataParam("name") String name) {

		try {

			File tmp = File.createTempFile("upl", ".jpdl.xml");
			IOUtils.copy(file, new FileOutputStream(tmp));
			
			if(processEngine == null)
				throw new ProcessEngineException("Fire! fire! mayday! mayday! we're going down!.. JBPM process engine is down!");
			
			String deploymentId = 
				processEngine.getRepositoryService().createDeployment()
                    .addResourceFromInputStream(name, new FileInputStream(tmp)).deploy();
            
            ProcessDefinition definition = processEngine.getRepositoryService()
                    .createProcessDefinitionQuery()
                    .deploymentId(deploymentId).uniqueResult();
            
            tmp.renameTo(new File(deploymentDir, definition.getId() + ".jpdl.xml"));


            return Response.ok(definition.getId()).build();
			
		} catch (IOException e) {
			// lol payment required :)
			throw new WebApplicationException(e,402);
		}
		
	}
	

	@GET
	@Path("deployment/{id}")
	@Produces("text/xml")
	public Deployment getDeployment(@PathParam("id") String id) {
		
		if(processEngine == null)
			throw new ProcessEngineException("Fire! fire! mayday! mayday! we're going down!.. JBPM process engine is down!");
		
		return new Deployment(processEngine.getRepositoryService().createDeploymentQuery().deploymentId(id).uniqueResult());
	}
	
	@GET
	@Path("deployment/{id}/jpdl")
	@Produces("text/xml")
	public String getJpdl(@PathParam("id") String id) {
		
		
		StringWriter writer = new StringWriter();
		FileInputStream fis;
		try {
			
			File f = new File(deploymentDir, id + ".jpdl.xml");
			fis = new FileInputStream(f);
			IOUtils.copy(fis, writer);
			String res = writer.toString();
			
			if(res.length() > 0) { 
				res = "<?xml version='1.0' encoding='UTF-8'?>" +
				"<?xml-stylesheet type='text/xsl' href='" + uriInfo.getBaseUri() + "resources/xslt/toSvg.xsl'?>" +
				res.substring(res.lastIndexOf("?>") + 2);
				return res;
			}
			return null;
			
		} catch (FileNotFoundException e1) {
			throw new WebApplicationException(e1,404);
		} catch (IOException e) {
			// lol payment required :)
			throw new WebApplicationException(e,402);
		} 
	}
}
